package tx.screens;

import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;

import tx.core.input.GameAction;
import tx.core.input.InputManager;
import tx.development.Development;
import tx.ui.ScreenManager;

/**
 * Class responsible for the Title screen of the game. 
 *  
 * @author Guilherme Mauro Germoglio Barbosa - germoglio@gmail.com
 */
public class TitleScreen implements Screen, ActionListener {

	
	/**
	 * High scores button base file name. 
	 */
	private static final String HIGH_SCORES_BUTTON_FILE_NAME = "title-high_scores";
	/**
	 * Options button base file name. 
	 */
	private static final String OPTIONS_BUTTON_FILE_NAME = "title-options";
	/**
	 * Quit button base file name. 
	 */
	private static final String QUIT_BUTTON_FILE_NAME = "title-quit";
	/**
	 * Play button base file name. 
	 */
	private static final String PLAY_BUTTON_FILE_NAME = "title-play";

	/**
	 * Buttons file name prefix.
	 */
	private static final String BUTTON_FILE_NAME_PREFIX = "images" + File.separator + "buttons" + File.separator;
	
	/**
	 * The background image.
	 */
	private Image bgImage;
	
	/**
	 * The GameAction for play.
	 */
	private GameAction playGameAction;
	/**
	 * The GameAction for options.
	 */
	private GameAction optionsGameAction;
	/**
	 * The GameAction for high scores.
	 */
	private GameAction highScoresGameAction;
	/**
	 * The GameAction for quit.
	 */
	private GameAction quitGameAction;
	/**
	 * The screen manager.
	 */
	private ScreenManager screenManager;
	/**
	 * This TitleScreen's InputManager. 
	 */
	private InputManager inputManager;
	/**
	 * The play button.
	 */
	private JButton playButton;
	/**
	 * The quit button.
	 */
	private JButton quitButton;
	/**
	 * The options button.
	 */
	private JButton optionsButton;
	/**
	 * The high scores button.
	 */
	private JButton highScoresButton;
	
	/**
	 * Is should be running. 
	 */
	private boolean isRunning;
	
	/**
	 * The next Screen that should be displayed.
	 */
	private Screen nextScreen;
	
	/**
	 * The GameScreen. It must be the nextScreen if the play button is pressed.
	 */
	private GameScreen gameScreen;

	/**
	 * Creates a TitleScreen.
	 * @param screenManager The ScreenManager the screen will use.
	 */
	public TitleScreen(ScreenManager screenManager) {
		this.screenManager = screenManager;
	}
	

	/**
	 * Sets the game screen.
	 * @param gameScreen The GameScreen.
	 */
	public void setGameScreen(GameScreen gameScreen) {
		this.gameScreen = gameScreen;
	}
	
	/**
	 * Inits the title screen.
	 */
	public void init() {
		initInputManager();
		
		initButtons();
		
		initScreen();
		
		isRunning = true;
		
		this.nextScreen = this;
	}

	/**
	 * Inits InputManager and GameActions.
	 */
	private void initInputManager() {
		inputManager = new InputManager(this.screenManager.getFullScreenWindow());
		
		this.playGameAction = new GameAction(PLAY_BUTTON_FILE_NAME, GameAction.DETECT_INITIAL_PRESS_ONLY);
		this.optionsGameAction = new GameAction(OPTIONS_BUTTON_FILE_NAME, GameAction.DETECT_INITIAL_PRESS_ONLY);
		this.highScoresGameAction = new GameAction("high scores", GameAction.DETECT_INITIAL_PRESS_ONLY);
		this.quitGameAction = new GameAction(QUIT_BUTTON_FILE_NAME, GameAction.DETECT_INITIAL_PRESS_ONLY);
		
		inputManager.mapToKey(quitGameAction, KeyEvent.VK_ESCAPE);
	}

	/**
	 * Sets the buttons in correct places and setups the frame.
	 */
	private void initScreen() {
		
		JFrame frame = screenManager.getFullScreenWindow();
		
		Container contentPane = frame.getContentPane();
		
		if (contentPane instanceof JComponent) {
			((JComponent)contentPane).setOpaque(false);
		}
		
		contentPane.setLayout(null);
		
		Insets insets = contentPane.getInsets();
		
		contentPane.add(playButton);
		contentPane.add(optionsButton);
		contentPane.add(highScoresButton);
		contentPane.add(quitButton);
		
		Dimension playButtonSize = playButton.getPreferredSize();
		int xPlayButton = 475 + insets.left;
		int yPlayButton = 375 + insets.top;
		playButton.setBounds(xPlayButton, yPlayButton, playButtonSize.width, playButtonSize.height);
		
		Dimension optionsButtonSize = optionsButton.getPreferredSize();
		int xOptionsButton = 440 + insets.left;
		int yOptionsButton = 407 + insets.top;
		optionsButton.setBounds(xOptionsButton, yOptionsButton, optionsButtonSize.width, optionsButtonSize.height);
		
		Dimension highScoresSize = highScoresButton.getPreferredSize();
		int xHighScoresButton = 405 + insets.left;
		int yHighScoresButton = 439 + insets.top;
		highScoresButton.setBounds(xHighScoresButton, yHighScoresButton, highScoresSize.width, highScoresSize.height);
		
		Dimension quitButtonSize = quitButton.getPreferredSize();
		int xQuitButton = 475 + insets.left;
		int yQuitButton = 471 + insets.top;
		quitButton.setBounds(xQuitButton, yQuitButton, quitButtonSize.width, quitButtonSize.height);
		
		frame.validate();

		bgImage = new ImageIcon(this.getClass().getResource( "images" + File.separator + "bgs" + File.separator + "title_screen_background.png")).getImage();
	}

	/**
	 * Inits the screens buttons.
	 */
	private void initButtons() {
		playButton = createButton(BUTTON_FILE_NAME_PREFIX + PLAY_BUTTON_FILE_NAME);
		quitButton = createButton(BUTTON_FILE_NAME_PREFIX + QUIT_BUTTON_FILE_NAME);
		optionsButton = createButton(BUTTON_FILE_NAME_PREFIX + OPTIONS_BUTTON_FILE_NAME);
		highScoresButton = createButton(BUTTON_FILE_NAME_PREFIX + HIGH_SCORES_BUTTON_FILE_NAME);
	}
	
	/**
	 * Creates a button for the title screen.
	 * @param imageName The image name of the button. It must be the base name, since the image must always
	 * be a PNG. It must be also reachable through TitleScreen.class.getResource(String) method.  
	 * @return A JButton.
	 */
	private JButton createButton(String imageName) {
		URL imagePath = this.getClass().getResource(imageName + ".png");
		ImageIcon iconRollover = new ImageIcon(imagePath);
		int w = iconRollover.getIconWidth();
		int h = iconRollover.getIconHeight();
		
		Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
		
		Image image = screenManager.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
		Graphics2D g = (Graphics2D)image.getGraphics();
		Composite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f);
		g.setComposite(alpha);
		g.drawImage(iconRollover.getImage(), 0, 0, null);
		g.dispose();
		ImageIcon iconDefault = new ImageIcon(image);
		
		image = screenManager.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
		g = (Graphics2D)image.getGraphics();
		g.drawImage(iconRollover.getImage(), 2, 2, null);
		g.dispose();
		ImageIcon iconPressed = new ImageIcon(image);
		
		JButton button = new JButton();
		button.addActionListener(this);
		button.setIgnoreRepaint(true);
		button.setFocusable(false);
		button.setBorder(null);
		button.setContentAreaFilled(false);
		button.setCursor(cursor);
		button.setIcon(iconDefault);
		button.setRolloverIcon(iconRollover);
		button.setPressedIcon(iconPressed);
		
		return button;
	}

	
	/* (non-Javadoc)
	 * @see tx.screens.Screen#update(long)
	 */
	public void update(long elapsedTime) {
		if (playGameAction.isPressed()) {
			if (Development.DEBUG_ENABLED) System.out.println( Development.DEBUG_LABEL + "TitleScreen.update()" + playGameAction);
			
			gameScreen.init();
			
			this.stop();
			
			this.nextScreen = gameScreen;
			
		}
		if (optionsGameAction.isPressed()) {
			if (Development.DEBUG_ENABLED) System.out.println( Development.DEBUG_LABEL + "TitleScreen.update()" + optionsGameAction);
		}
		if (highScoresGameAction.isPressed()) {
			if (Development.DEBUG_ENABLED) System.out.println( Development.DEBUG_LABEL + "TitleScreen.update()" + highScoresGameAction);
		}
		if (quitGameAction.isPressed()) {
			if (Development.DEBUG_ENABLED) System.out.println( Development.DEBUG_LABEL + "TitleScreen.update()" + quitGameAction);
			
			isRunning = false;
		}
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		Object src = e.getSource();
		if (src == playButton) {
			playGameAction.tap();
		} else if (src == optionsButton) {
			optionsGameAction.tap();
		} else if (src == highScoresButton) {
			highScoresGameAction.tap();
		} else if (src == quitButton) {
			quitGameAction.tap();
		}
	}
	
    
    /* (non-Javadoc)
     * @see tx.screens.Screen#draw(java.awt.Graphics2D)
     */
    public void draw(Graphics2D g) {
    	g.drawImage(bgImage, 0, 0, null);
    	
    	JFrame frame = screenManager.getFullScreenWindow(); 
    // the layered pane contains things like popups (tooltips, 
    // popup menus) and the content pane. 
    	frame.getLayeredPane().paintComponents(g); 
    } 
	
	/* (non-Javadoc)
	 * @see tx.screens.Screen#isRunning()
	 */
	public boolean isRunning() {
		return this.isRunning;
	}

	/* (non-Javadoc)
	 * @see tx.screens.Screen#nextScreen()
	 */
	public Screen nextScreen() {
		return this.nextScreen;
	}


	/* (non-Javadoc)
	 * @see tx.screens.Screen#stop()
	 */
	public void stop() {
		JFrame frame = screenManager.getFullScreenWindow();
		
		Container contentPane = frame.getContentPane();
		
		
		contentPane.remove(playButton);
		contentPane.remove(optionsButton);
		contentPane.remove(highScoresButton);
		contentPane.remove(quitButton);
		
		frame.validate();
		
		playButton = null;
		optionsButton = null;
		highScoresButton = null;
		quitButton = null;

		bgImage = null;
	}
}
